/**
 * Created with IntelliJ IDEA.
 * User: seth.yang
 * Date: 15-1-10
 * Time: 上午3:50
 * To change this template use File | Settings | File Templates.
 */
var sun = {name:'太阳(Sun)', r:109.1, dip:0, t:0, m:332946},
    Planets = [
        {name:'水星(Mercury)',  r:0.38, dip:7,     t:0.38,   m:0.0553},
        {name:'金星(Venus)',    r:0.95, dip:3.4,   t:0.72,   m:0.8150},
        {name:'地球(Earth)',    r:1.00, dip:7.25,  t:1,      m:1},
        {name:'火星(Mars)',     r:0.53, dip:1.8,   t:1.52,   m:0.1074},
        {name:'木星(Jupiter)',  r:11.2, dip:1.3,   t:5.20,   m:317.833},
        {name:'土星(Saturn)',   r:9.5,  dip:2.5,   t:9.54,   m:95.159},
        {name:'天王星(Uranus)', r:14.5, dip:0.8,   t:19.218, m:14.5},
        {name:'海王星(Neptune)',r:3.9,  dip:1.769, t:30.06,  m:17.1},
        {name:'冥王星(Pluto)',  r:0.178,dip:17.15, t:39.956, m:0.0024}
    ];

window.onload = function () {
    var Point = function (x, y) {
            this.x = x || 0;
            this.y = y || 0;
        },Vector = function (x, y, z) {
            this.x = x || 0;
            this.y = y || 0;
            this.z = z || 0;
        }, Sphere = function (v, r) {
            this.vector = v;
            this.r = r;
        };

    var ctx = document.getElementById ('ctx'), g = ctx.getContext ('2d'),
        o = new Vector (0, 0, 0), ball = new Sphere (o, 100),
        W = ctx.clientWidth, H = ctx.clientHeight, PI2 = 2 * Math.PI, ANGLE = PI2/360,
        alpha = 5 * Math.PI / 30, C = {x:0, y:0, z:1000}, h = 500;

    function projection (h, camera, v) {
        v.x = v.x * h / Math.abs (camera.z - v.z);
        v.y = v.y * h / Math.abs (camera.z - v.z);
    }

    function rotateX (v, alpha) {
        var y = v.y, z = v.z;
        v.y = y * Math.cos (alpha) - z * Math.sin (alpha);
        v.z = y * Math.sin (alpha) + z * Math.cos (alpha);
    }

    function rotateY (v, alpha) {
        var x = v.x, z = v.z;
        v.x = z * Math.cos (alpha) + x * Math.cos (alpha);
        v.z = z * Math.sin (alpha) - x * Math.sin (alpha);
    }

    function rotateZ (v, alpha) {
        var x = v.x, y = v.y;
        v.x = x * Math.cos (alpha) - y * Math.sin (alpha);
        v.y = x * Math.sin (alpha) + y * Math.cos (alpha);
    }

    function drawTrack (g, r, a, color) {
        g.fillStyle = color;
        var x = r, y = 0, v;
        g.moveTo (x, y);
        g.beginPath ();
        for (var i = 0; i < PI2; i += ANGLE) {
            x = r * Math.cos (i);
            y = r * Math.sin (i);
            v = {x:x, y:y, z:0};
            rotateX (v, a);
            projection (h, C, v);
            g.lineTo (v.x, v.y);
        }
        g.fill ();
    }

    function drawPane (g, rect, rotation, color) {
        g.strokeStyle = color;
        var lines = [[],[]], x, y, i, j, step = 20;
        lines[0].push (
            {x:rect.x,y:rect.y,z:0},
            {x:rect.x,y:rect.y + rect.h,z:0},
            {x:rect.x + rect.w, y:rect.y + rect.h, z:0},
            {x:rect.x + rect.w, y:rect.y, z:0},
            {x:rect.x, y:rect.y, z:0}
        );
        lines[1].push (
            {x:rect.x,y:rect.y,z:80},
            {x:rect.x,y:rect.y + rect.h,z:80},
            {x:rect.x + rect.w, y:rect.y + rect.h, z:80},
            {x:rect.x + rect.w, y:rect.y, z:80},
            {x:rect.x, y:rect.y, z:80}
        );

        for (i = 0; i < lines.length; i ++) {
            for (j = 0; j < lines[i].length; j ++) {
                if (rotation.x) {
                    rotateX (lines[i][j], rotation.x);
                }
                if (rotation.y) {
                    rotateY (lines[i][j], rotation.y);
                }
                if (rotation.z) {
                    rotateZ (lines[i][j], rotation.z);
                }
                projection (h, C, lines [i][j]);
            }
        }

        for (i = 0; i < lines.length; i ++) {
            g.moveTo (lines [i][0].x, lines [i][0].y);
            g.beginPath ();
            for (j = 0; j < lines[i].length; j ++) {
                g.lineTo (lines [i][j].x, lines[i][j].y);
            }
            g.lineTo (lines [i][0].x, lines[i][0].y);
            g.stroke();
        }

        lines = [[],[]];
        for (x = rect.x + step; x < rect.x + rect.w; x += step) {
            lines[0].push ({a:{x:x,y:rect.y,z:0}, z:{x:x, y:rect.y + rect.h,z:0}});
            lines[1].push ({a:{x:x,y:rect.y,z:80}, z:{x:x, y:rect.y + rect.h,z:80}});
        }
        for (y = rect.y + step; y < rect.y + rect.h; y += step) {
            lines[0].push ({a:{x:rect.x,y:y,z:0}, z:{x:rect.x + rect.w, y:y,z:0}});
            lines[1].push ({a:{x:rect.x,y:y,z:80}, z:{x:rect.x + rect.w, y:y,z:80}});
        }
        for (i = 0; i < lines.length; i ++) {
            for (j = 0; j < lines[i].length; j ++) {
                var line = lines [i][j];
                if (rotation.x) {
                    rotateX (line.a, rotation.x);
                    rotateX (line.z, rotation.x);
                }
                if (rotation.y) {
                    rotateY (line.a, rotation.y);
                    rotateY (line.z, rotation.y);
                }
                if (rotation.z) {
                    rotateZ (line.a, rotation.z);
                    rotateZ (line.z, rotation.z);
                }

                projection (h, C, line.a);
                projection (h, C, line.z);
                g.beginPath ();
                g.moveTo (line.a.x, line.a.y);
                g.lineTo (line.z.x, line.z.y);
                g.stroke();
                g.closePath ();
            }
        }
    }

    g.translate (W/2, H/2);

    var rect = {x:-W/2,y:-H/2,w:W,h:H}, a = 0,
        rotation = {x:0,y:0,z:0}, point = {x:0,y:0}, hold = false,
        autoPlay = false;

    var update = function () {
        g.clearRect (-W/2, -H/2, W, H);
        var a = document.getElementById ('a'),
            x = document.getElementById ('x'),
            y = document.getElementById ('y'),
            z = document.getElementById ('z');
        if (a.checked) {
            if (x.checked) rotation.x += ANGLE;
            if (y.checked) rotation.y += ANGLE;
            if (z.checked) rotation.z += ANGLE;
        }
        drawPane (g, rect, rotation, 'rgba(200,200,255,0.5)');
        if (a.checked) {
            requestAnimationFrame (update);
        }
    };
    update ();

    document.onmousedown = function (e) {
        point.x = e.x || e.clientX;
        point.y = e.y || e.clientY;
        hold = true;
    };

    document.onmousemove = function (e) {
        if (!hold) return;
        var ex = document.getElementById ('x'), ey = document.getElementById ('y');
        if (!ex.checked && !ey.checked) return;


        var x = e.x || e.clientX, y = e.y || e.clientY,
            dx = point.x - x, dy = point.y - y,
            xd = dx > 0 ? 1 : -1,
            yd = dy > 0 ? 1 : -1;
        if (ex.checked)
            rotation.x += xd * Math.atan2 (dy, h);
        if (ey.checked)
            rotation.y += yd * Math.atan2 (dx, h);
        point.x = x;
        point.y = y;
        if (!autoPlay)
            update ();
    };

    document.onmouseout = function (e) {
        point = {x:0, y:0};
        hold = false;
    };

    document.onmouseup = function (e) {
        point = {x:0, y:0};
        hold = false;
    };

    document.onmousewheel = function (e) {
        var value;
        if(e.wheelDelta) {
            value = Math.abs (e.wheelDelta) / e.wheelDelta;
        } else {
            value = e.detail;
        }
        h += value * 20;
        if (!autoPlay)
            update ();
    };

    document.getElementById ('reset').onclick = function () {
        rotation = {x:0,y:0,z:0};
        if (!autoPlay)
            update ();
    };
    document.getElementById ('a').onclick = function () {
        update ();
        autoPlay = this.checked;
    };
};